package cn.xorange.commons.core.exception;

import cn.xorange.commons.core.basic.bean.ResultBean;
import cn.xorange.commons.core.basic.bean.SystemCode;
import cn.xorange.commons.exception.DataException;
import cn.xorange.commons.utils.exception.BaseException;
import cn.xorange.commons.utils.exception.ExceptionUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import java.sql.SQLException;

/**
 * 全局异常处理
 *
 * @author yangjian
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(NoHandlerFoundException.class)
    public ResultBean noFoundExceptionHandler(Exception e, HttpServletRequest request) {
        BaseException baseException = SysException.pathNotFound(request.getRequestURI());
        ExceptionUtils.printLog(baseException);
        return ResultBean.onFail(baseException);
    }

    /**
     * 空指针异常处理（防止拦截器未拦击到的错误）
     */
    @ExceptionHandler(NullPointerException.class)
    public ResultBean nullPointExceptionHandler(RuntimeException e){
        BaseException baseException = SysException.nullPointException(e);
        ExceptionUtils.printLog(baseException);
        return ResultBean.onFail(baseException);
    }


    @ExceptionHandler(ConstraintViolationException.class)
    public ResultBean handleValidException(ConstraintViolationException e){
        /** 日志记录错误信息
        //String defaultMessage = e.getBindingResult().getFieldError().getDefaultMessage();
        //log.error("字段有效性检查错误：{}",defaultMessage);
        // 将错误信息返回给前台 */
        return ResultBean.onFail();
    }


    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResultBean handleMethodValidException(MethodArgumentNotValidException e){
        // 日志记录错误信息
        String defaultMessage = e.getBindingResult().getFieldError().getDefaultMessage();
        log.error("字段有效性检查错误：{}",defaultMessage);
        // 将错误信息返回给前台
        return ResultBean.onFail(defaultMessage);
    }


    //@ExceptionHandler(java.sql.SQLIntegrityConstraintViolationException.class)
    //public ResultBean sqlIntegrityConstraintViolationException(RuntimeException e){
    //    return ResultBean.onFail( DataException.sqlError(e));
    //}

    @ExceptionHandler(org.springframework.dao.DuplicateKeyException.class)
    public ResultBean duplicateKeyException(Throwable throwable){

        DataException ex = DataException.duplicateKeyException(throwable);
        ExceptionUtils.printLog(ex);
        return ResultBean.onFail(ex);
    }

    @ExceptionHandler(SQLException.class)
    public ResultBean sqlException(RuntimeException e){
        return ResultBean.onFail( DataException.sqlError(e));
    }



    @ExceptionHandler(org.mybatis.spring.MyBatisSystemException.class)
    public ResultBean myBatisException(BaseException ex){
        ExceptionUtils.printLog(ex);
        return ResultBean.onFail(ex);
    }



    @ExceptionHandler(BaseException.class)
    public ResultBean baseException(BaseException ex){
        ExceptionUtils.printLog(ex);
        return ResultBean.onFail(ex);
    }



    /**
     * 系统异常处理器
     * @param throwable
     * @return
     */
    @ExceptionHandler(Throwable.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)   // 指定http状态码，如果不指定为非2xx，feign不会抛出异常
    public ResultBean systemExceptionHandler(Throwable throwable) {

        SystemCode code = SystemCode.SYSTEM_EXCEPTION;
        code.setMsg(throwable.getMessage());
        SysException exception = new SysException(code);
        ExceptionUtils.printLog(exception);
        return ResultBean.onFail(exception);
    }




}
